package com.kikcn.jpa;

import com.kikcn.jpa.entity.Privilege;
import com.kikcn.jpa.entity.Resource;
import com.kikcn.jpa.entity.Role;
import com.kikcn.jpa.entity.User;
import com.kikcn.jpa.repo.PrivilegeRepository;
import com.kikcn.jpa.repo.ResourceRepository;
import com.kikcn.jpa.repo.RoleRepository;
import com.kikcn.jpa.repo.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.thymeleaf.expression.Sets;

import javax.transaction.Transactional;
import java.util.*;

/**
 * User: Yubin Lai
 * Date: 2017/8/29
 * Time: 20:59
 */
@Component
public class InitDataLoader implements
        ApplicationListener<ContextRefreshedEvent> {

    boolean alreadySetup = false;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private PrivilegeRepository privilegeRepository;
    @Autowired
    private ResourceRepository resourceRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    @Transactional
    public void onApplicationEvent(ContextRefreshedEvent event) {

        if (alreadySetup)
            return;
        Privilege readPrivilege
                = createPrivilegeIfNotFound("READ_PRIVILEGE");
        Privilege writePrivilege
                = createPrivilegeIfNotFound("WRITE_PRIVILEGE");

        List<Resource> resources=new ArrayList();
        resources.add(new Resource("/page1"));
        resources.add(new Resource("/page2"));
        resources.add(new Resource("/page3"));
        resourceRepository.save(resources);

        List<Privilege> adminPrivileges = Arrays.asList(
                readPrivilege, writePrivilege);
        createRoleIfNotFound("ROLE_ADMIN", adminPrivileges);
        createRoleIfNotFound("ROLE_USER", Arrays.asList(readPrivilege));



        Resource r1=resourceRepository.findByUrl("/page1");
        resourceRepository.save(r1);
        Resource r2=resourceRepository.findByUrl("/page2");
        resourceRepository.save(r2);
        Resource r3=resourceRepository.findByUrl("/page3");
        resourceRepository.save(r3);

        Role role_p1=createRoleIfNotFound("ROLE_PAGE1", null);
        role_p1.getResources().add(r1);
        roleRepository.save(role_p1);
        Role role_p2=createRoleIfNotFound("ROLE_PAGE2", null);
        role_p2.getResources().add(r2);
        roleRepository.save(role_p2);
        Role role_p_all=createRoleIfNotFound("ROLE_PAGE_ALL", null);
        role_p_all.getResources().add(r1);
        role_p_all.getResources().add(r2);
        role_p_all.getResources().add(r3);
        roleRepository.save(role_p_all);

        Role adminRole = roleRepository.findByName("ROLE_ADMIN");
        User user = new User();
        user.setFirstName("Test");
        user.setLastName("Test");
        user.setPassword(passwordEncoder.encode("test"));
        user.setEmail("test@test.com");
        user.setRoles(Arrays.asList(adminRole, role_p_all));
        user.setEnabled(true);
        userRepository.save(user);
        User user2 = new User();
        user2.setFirstName("Test2");
        user2.setLastName("Test2");
        user2.setPassword(passwordEncoder.encode("test2"));
        user2.setEmail("test2@test.com");
        user2.setRoles(Arrays.asList( role_p1));
        user2.setEnabled(true);
        userRepository.save(user2);
        alreadySetup = true;
    }

    @Transactional
    private Privilege createPrivilegeIfNotFound(String name) {

        Privilege privilege = privilegeRepository.findByName(name);
        if (privilege == null) {
            privilege = new Privilege(name);
            privilegeRepository.save(privilege);
        }
        return privilege;
    }

    @Transactional
    private Role createRoleIfNotFound(
            String name, Collection<Privilege> privileges) {

        Role role = roleRepository.findByName(name);
        if (role == null) {
            role = new Role(name);
            role.setPrivileges(privileges);
            roleRepository.save(role);
        }
        return role;
    }

    @Transactional
    private Resource createResourceIfNotFound(
            String url, Set<Role> roles) {

        Resource resource = resourceRepository.findByUrl(url);
        resource.setRoles(roles);
        return resource;
    }
}